const fastify = require('fastify');
const path = require('path');

// 创建 Fastify 应用实例
function createApp(options = {}) {
  const app = fastify({
    logger: process.env.NODE_ENV === 'development' ? {
      level: process.env.LOG_LEVEL || 'info',
      transport: {
        target: 'pino-pretty',
        options: {
          colorize: true
        }
      }
    } : {
      level: process.env.LOG_LEVEL || 'info'
    },
    trustProxy: true,
    ...options
  });

  // 注册插件和中间件
  async function registerPlugins() {
    try {
      // 注册 CORS
      await app.register(require('@fastify/cors'), {
        origin: (origin, callback) => {
          const allowedOrigins = (process.env.CORS_ORIGIN || 'http://localhost:3000').split(',');
          
          // 允许没有 origin 的请求（如移动应用或 Postman）
          if (!origin) return callback(null, true);
          
          const isAllowed = allowedOrigins.some(pattern => {
            if (pattern === '*') return true;
            if (pattern.includes('*')) {
              const regex = new RegExp(pattern.replace(/\*/g, '.*'));
              return regex.test(origin);
            }
            return pattern === origin;
          });
          
          callback(null, isAllowed);
        },
        credentials: true,
        methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH']
      });
      app.log.info('CORS plugin registered');

      // 注册 Helmet 安全头
      await app.register(require('@fastify/helmet'), {
        contentSecurityPolicy: {
          directives: {
            defaultSrc: ["'self'"],
            styleSrc: ["'self'", "'unsafe-inline'"],
            scriptSrc: ["'self'"],
            imgSrc: ["'self'", "data:", "https:"],
            connectSrc: ["'self'"],
            fontSrc: ["'self'"],
            objectSrc: ["'none'"],
            mediaSrc: ["'self'"],
            frameSrc: ["'none'"]
          }
        },
        crossOriginEmbedderPolicy: false
      });
      app.log.info('Helmet plugin registered');

      // 注册速率限制
      await app.register(require('@fastify/rate-limit'), {
        max: parseInt(process.env.RATE_LIMIT_MAX) || 100,
        timeWindow: parseInt(process.env.RATE_LIMIT_WINDOW) || 60000, // 1 minute
        skipOnError: true,
        errorResponseBuilder: (request, context) => {
          return {
            success: false,
            message: 'Rate limit exceeded',
            error: {
              statusCode: 429,
              retryAfter: Math.round(context.ttl / 1000),
              limit: context.max,
              remaining: context.remaining,
              reset: new Date(Date.now() + context.ttl)
            }
          };
        }
      });
      app.log.info('Rate limit plugin registered');

      // 暂时跳过 Cookie 插件，存在兼容性问题
      // try {
      //   await app.register(require('@fastify/cookie'), {
      //     secret: process.env.COOKIE_SECRET || 'your-cookie-secret-key'
      //   });
      //   app.log.info('Cookie plugin registered');
      // } catch (error) {
      //   app.log.error('Cookie plugin error:', error.message || 'Unknown error');
      //   app.log.error('Cookie plugin stack:', error.stack || 'No stack trace');
      //   app.log.error('Cookie plugin full error:', JSON.stringify(error, null, 2));
      //   throw error;
      // }

      // 注册 JWT
      await app.register(require('@fastify/jwt'), {
        secret: process.env.JWT_SECRET || 'your-jwt-secret-key',
        sign: {
          expiresIn: process.env.JWT_EXPIRES_IN || '15m'
        },
        verify: {
          extractToken: (request) => {
            // 从 Authorization header 提取 token
            const authHeader = request.headers.authorization;
            if (authHeader && authHeader.startsWith('Bearer ')) {
              return authHeader.substring(7);
            }
            return null;
          }
        }
      });
      app.log.info('JWT plugin registered');

      // 注册静态文件服务（如果需要）
      if (process.env.SERVE_STATIC === 'true') {
        try {
          await app.register(require('@fastify/static'), {
            root: path.join(__dirname, '../public'),
            prefix: '/public/'
          });
          app.log.info('Static files plugin registered');
        } catch (error) {
          app.log.error('Static files plugin error:', error.message || 'Unknown error');
          app.log.error('Static files plugin stack:', error.stack || 'No stack trace');
          throw error;
        }
      }
    } catch (error) {
      app.log.error('Error in registerPlugins:', error.message);
      app.log.error('Plugin registration stack:', error.stack);
      throw error;
    }
  }

  // 注册全局错误处理
  function registerErrorHandlers() {
    // 全局错误处理器
    app.setErrorHandler(async (error, request, reply) => {
      request.log.error(error);

      // JWT 错误
      if (error.code === 'FST_JWT_BAD_REQUEST' || 
          error.code === 'FST_JWT_NO_AUTHORIZATION_IN_HEADER' ||
          error.code === 'FST_JWT_AUTHORIZATION_TOKEN_EXPIRED' ||
          error.code === 'FST_JWT_AUTHORIZATION_TOKEN_INVALID') {
        return reply.code(401).send({
          success: false,
          message: 'Authentication failed',
          error: {
            statusCode: 401,
            code: error.code,
            message: error.message
          }
        });
      }

      // 验证错误
      if (error.validation) {
        return reply.code(400).send({
          success: false,
          message: 'Validation error',
          error: {
            statusCode: 400,
            validation: error.validation,
            validationContext: error.validationContext
          }
        });
      }

      // MongoDB 错误
      if (error.name === 'MongoError' || error.name === 'MongooseError') {
        if (error.code === 11000) {
          return reply.code(409).send({
            success: false,
            message: 'Duplicate key error',
            error: {
              statusCode: 409,
              field: Object.keys(error.keyPattern || {})[0]
            }
          });
        }
        
        return reply.code(500).send({
          success: false,
          message: 'Database error',
          error: {
            statusCode: 500,
            message: process.env.NODE_ENV === 'development' ? error.message : 'Internal server error'
          }
        });
      }

      // 默认错误处理
      const statusCode = error.statusCode || 500;
      
      return reply.code(statusCode).send({
        success: false,
        message: error.message || 'Internal server error',
        error: {
          statusCode,
          code: error.code,
          message: process.env.NODE_ENV === 'development' ? error.message : 'Internal server error'
        }
      });
    });

    // 404 处理在路由中定义
  }

  // 注册钩子
  function registerHooks() {
    // 请求日志
    app.addHook('onRequest', async (request, reply) => {
      request.startTime = Date.now();
    });

    // 响应日志
    app.addHook('onSend', async (request, reply, payload) => {
      const responseTime = Date.now() - request.startTime;
      
      request.log.info({
        method: request.method,
        url: request.url,
        statusCode: reply.statusCode,
        responseTime: `${responseTime}ms`,
        userAgent: request.headers['user-agent'],
        ip: request.ip
      }, 'Request completed');
      
      return payload;
    });

    // 关闭钩子
    app.addHook('onClose', async (instance, done) => {
      instance.log.info('Server is closing...');
      
      // 关闭数据库连接
      const mongoose = require('mongoose');
      if (mongoose.connection.readyState === 1) {
        await mongoose.connection.close();
        instance.log.info('Database connection closed');
      }
      
      done();
    });
  }

  // 初始化应用
  async function init() {
    try {
      // 连接数据库
      const { connectDB } = require('./config/database');
      await connectDB();
      
      // 注册插件
      try {
        await registerPlugins();
        app.log.info('Plugins registered successfully');
      } catch (pluginError) {
        app.log.error('Failed to register plugins:', pluginError.message);
        app.log.error('Plugin error stack:', pluginError.stack);
        throw pluginError;
      }
      
      // 注册错误处理
      registerErrorHandlers();
      
      // 注册钩子
      registerHooks();
      
      // 注册路由
      try {
        console.log('Attempting to register routes...');
        await app.register(require('./routes'), { prefix: '/api/v1' });
        app.log.info('Routes registered successfully');
      } catch (routeError) {
        console.error('Route registration error:', routeError);
        app.log.error('Failed to register routes:', routeError.message);
        app.log.error('Route error stack:', routeError.stack);
        app.log.error('Route error full details:', JSON.stringify(routeError, null, 2));
        throw routeError;
      }
      
      app.log.info('Application initialized successfully');
      
    } catch (error) {
      app.log.error('Failed to initialize application:', error.message);
      app.log.error('Error stack:', error.stack);
      throw error;
    }
  }

  // 启动服务器
  async function start() {
    try {
      await init();
      
      const host = process.env.HOST || '0.0.0.0';
      const port = parseInt(process.env.PORT) || 3000;
      
      await app.listen({ host, port });
      
      app.log.info(`Server listening on http://${host}:${port}`);
      
      if (process.env.NODE_ENV !== 'production') {
        app.log.info(`Swagger documentation available at http://${host}:${port}/docs`);
      }
      
    } catch (error) {
      app.log.error('Failed to start server:', error);
      process.exit(1);
    }
  }

  // 优雅关闭
  function setupGracefulShutdown() {
    const signals = ['SIGINT', 'SIGTERM'];
    
    signals.forEach(signal => {
      process.on(signal, async () => {
        app.log.info(`Received ${signal}, shutting down gracefully...`);
        
        try {
          await app.close();
          app.log.info('Server closed successfully');
          process.exit(0);
        } catch (error) {
          app.log.error('Error during shutdown:', error);
          process.exit(1);
        }
      });
    });
    
    // 处理未捕获的异常
    process.on('uncaughtException', (error) => {
      app.log.fatal('Uncaught exception:', error);
      process.exit(1);
    });
    
    process.on('unhandledRejection', (reason, promise) => {
      app.log.fatal('Unhandled rejection at:', promise, 'reason:', reason);
      process.exit(1);
    });
  }

  return {
    app,
    init,
    start,
    setupGracefulShutdown
  };
}

module.exports = createApp;